/*
 * Copyright 2001-2008 Aqris Software AS. All rights reserved.
 * 
 * This program is dual-licensed under both the Common Development
 * and Distribution License ("CDDL") and the GNU General Public
 * License ("GPL"). You may elect to use one or the other of these
 * licenses.
 */
package net.sf.refactorit.ui.module.createmissingmethod;

import net.sf.refactorit.refactorings.createmissing.CreateMethodContext;
import net.sf.refactorit.ui.DialogManager;
import net.sf.refactorit.ui.dialog.RitDialog;
import net.sf.refactorit.ui.module.RefactorItContext;
import net.sf.refactorit.ui.table.BinTable;
import net.sf.refactorit.utils.SwingUtil;

import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.ListSelectionModel;
import javax.swing.event.ListSelectionEvent;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableModel;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;


/**
 *
 * @author  tanel
 */
public class CreateMissingMethodDialog implements CreateMethodContext.ChangeListener {
  final RitDialog dialog;

  private boolean okPressed;

  RefactorItContext context;
//  MethodNotFoundError error;
//  int defaultModifier;
//  private int [] modifiers;
  private CreateMethodContext[] nodes;
  JTable methodTable;
  CreateMissingMethodPanel detailsPanel;

  //int selectedNodeIndex = -1;

  /** Creates new form CreateMissingMethodDialog */
  public CreateMissingMethodDialog(
      RefactorItContext context, CreateMethodContext[] nodes
  ) {
    dialog = RitDialog.create(context);

    this.context = context;
    this.nodes = nodes;

    initComponents();
    initContentPanels();
    
    SwingUtil.initCommonDialogKeystrokes(dialog,
        okButton, cancelButton, helpButton, new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        cancelButtonActionPerformed(e);
      }
    } );
    
    SwingUtil.invokeLater(new Runnable() {
      public void run() {
        detailsPanel.requestFocusForReturnTypeField();
      }
    } );
  }

  private void initListeners() {
    for (int i = 0; i < nodes.length; i++) {
      nodes[i].addChangeListener(this);
    }
  }

  private void removeListeners() {
    for (int i = 0; i < nodes.length; i++) {
      nodes[i].removeChangeListener(this);
    }
  }

  public void contextChanged() {
    // TODO: optimize this
    methodTable.repaint();
    for (int i = 0; i < nodes.length; i++) {
      if ((nodes[i].isSelected()) && (!nodes[i].checkReturnType())) {
        okButton.setEnabled(false);
        return;
      }
    }
    okButton.setEnabled(true);
  }

  /** This method is called from within the constructor to
   * initialize the form.
   * WARNING: Do NOT modify this code. The content of this method is
   * always regenerated by the Form Editor.
   */
  private void initComponents() {//GEN-BEGIN:initComponents
    java.awt.GridBagConstraints gridBagConstraints;

    downPanel = new java.awt.Panel();
    buttonPanel = new java.awt.Panel();
    okButton = new javax.swing.JButton();
    cancelButton = new javax.swing.JButton();
    helpButton = new javax.swing.JButton();
    mainPanel = new javax.swing.JPanel();
    jPanel1 = new javax.swing.JPanel();
    tablePanel = new javax.swing.JPanel();
    detailsContainer = new javax.swing.JPanel();

    dialog.setTitle("Create unknown method");
    dialog.addWindowListener(new java.awt.event.WindowAdapter() {
      public void windowClosing(java.awt.event.WindowEvent evt) {
        closeDialog(evt);
      }
    });

    downPanel.setLayout(new java.awt.GridBagLayout());

    okButton.setText("OK");
    okButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        okButtonActionPerformed(evt);
      }
    });

    buttonPanel.add(okButton);

    cancelButton.setText("Cancel");
    cancelButton.addActionListener(new java.awt.event.ActionListener() {
      public void actionPerformed(java.awt.event.ActionEvent evt) {
        cancelButtonActionPerformed(evt);
      }
    });

    buttonPanel.add(cancelButton);

    helpButton.setText("Help");
    buttonPanel.add(helpButton);

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.anchor = java.awt.GridBagConstraints.EAST;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.weighty = 1.0;
    gridBagConstraints.insets = new java.awt.Insets(3, 10, 3, 20);
    downPanel.add(buttonPanel, gridBagConstraints);

    dialog.getContentPane().add(downPanel, java.awt.BorderLayout.SOUTH);

    mainPanel.setLayout(new java.awt.BorderLayout());

    mainPanel.setBorder(new javax.swing.border.EtchedBorder());
    jPanel1.setLayout(new java.awt.GridBagLayout());

    tablePanel.setLayout(new java.awt.BorderLayout());

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.anchor = java.awt.GridBagConstraints.WEST;
    gridBagConstraints.weightx = 0.5;
    gridBagConstraints.weighty = 1.0;
    jPanel1.add(tablePanel, gridBagConstraints);

    detailsContainer.setLayout(new java.awt.BorderLayout());

    gridBagConstraints = new java.awt.GridBagConstraints();
    gridBagConstraints.fill = java.awt.GridBagConstraints.BOTH;
    gridBagConstraints.ipadx = 1;
    gridBagConstraints.ipady = 1;
    gridBagConstraints.weightx = 1.0;
    gridBagConstraints.weighty = 1.0;
    jPanel1.add(detailsContainer, gridBagConstraints);

    mainPanel.add(jPanel1, java.awt.BorderLayout.CENTER);

    dialog.getContentPane().add(mainPanel, java.awt.BorderLayout.CENTER);

    dialog.setSize(620, 470);
  }//GEN-END:initComponents

  void cancelButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
    dialog.dispose();
  }//GEN-LAST:event_cancelButtonActionPerformed

  void okButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_okButtonActionPerformed
    okPressed = true;
    // save the last edits
    detailsPanel.onExit(nodes[methodTable.getSelectedRow()]);
    dialog.dispose();
  }//GEN-LAST:event_okButtonActionPerformed

  /** Closes the dialog */
  void closeDialog(WindowEvent evt) {//GEN-FIRST:event_closeDialog
    dialog.dispose();
  }//GEN-LAST:event_closeDialog

  private void initContentPanels() {
    mainPanel.add(DialogManager.getHelpPanel("Create missing method"),
        BorderLayout.NORTH);
    
    detailsPanel = new CreateMissingMethodPanel(context, nodes[DEFAULT_METHODPANEL_ROW]);

    final CreateMissingMethodModel model = new CreateMissingMethodModel(context,
        nodes);
    //model.setDialog(this);
    methodTable = new JMethodTable(model, detailsPanel, nodes);
    methodTable.setDefaultRenderer(
        String.class, new MethodTableRenderer());

//    methodTable.setDefaultRenderer(
//        Boolean.class, new ExtractSTableRenderer());
//    membersTable.setDefaultRenderer(
//        ExtractableMemberNode.class, new ExtractSTableRenderer());
    methodTable.getTableHeader().setReorderingAllowed(false);
    methodTable.setAutoResizeMode(JTable.AUTO_RESIZE_NEXT_COLUMN);
    methodTable.getSelectionModel().setSelectionMode(ListSelectionModel.
        SINGLE_SELECTION);

    tablePanel.add(new JScrollPane(methodTable), BorderLayout.CENTER);
    fixColumnSizes();
    detailsContainer.add(detailsPanel, BorderLayout.CENTER);
    //mainPanel.add(new JCreateMissingMethodPanel(context, error, modifiers, defaultModifier), java.awt.BorderLayout.CENTER);
  }

  private void fixColumnSizes() {
    int width = 20;
    methodTable.getColumn(methodTable.getColumnName(0)).setMinWidth(2);
    methodTable.getColumn(methodTable.getColumnName(0)).setPreferredWidth(width);
    methodTable.getColumn(methodTable.getColumnName(0)).setWidth(width);
    methodTable.getColumn(methodTable.getColumnName(0)).setMaxWidth(width);
    methodTable.getColumn(methodTable.getColumnName(0)).setResizable(false);
    methodTable.getColumn(methodTable.getColumnName(0)).setMinWidth(2);
    methodTable.getColumn(methodTable.getColumnName(1)).setPreferredWidth(50);
    methodTable.getColumn(methodTable.getColumnName(1)).setWidth(50);
    methodTable.getColumn(methodTable.getColumnName(1)).setMaxWidth(150);
    methodTable.getColumn(methodTable.getColumnName(1)).setResizable(false);
  }

  public void show() {
    initListeners();
    contextChanged();
    methodTable.changeSelection(DEFAULT_METHODPANEL_ROW, DEFAULT_METHODPANEL_COLUMN, false, false);
    dialog.show();
    removeListeners();
  }

  /**
   * @param args the command line arguments
   */
  public static void main(String args[]) {
    //new CreateMissingMethodDialog(new javax.swing.JFrame(), true).show();
  }

  // Variables declaration - do not modify//GEN-BEGIN:variables
  private javax.swing.JPanel tablePanel;
  private javax.swing.JButton okButton;
  private javax.swing.JPanel mainPanel;
  private javax.swing.JButton cancelButton;
  private javax.swing.JPanel detailsContainer;
  private javax.swing.JPanel jPanel1;
  private java.awt.Panel buttonPanel;
  private javax.swing.JButton helpButton;
  private java.awt.Panel downPanel;
  private static final int DEFAULT_METHODPANEL_ROW = 0;
  private static final int DEFAULT_METHODPANEL_COLUMN = 0;
  // End of variables declaration//GEN-END:variables

  private static class JMethodTable extends BinTable {

    int selectedNodeIndex = -1;
    CreateMissingMethodPanel panel;
    CreateMethodContext[] nodes;

    public JMethodTable(TableModel model, CreateMissingMethodPanel panel,
        CreateMethodContext[] nodes) {
      super(model);
      this.panel = panel;
      this.nodes = nodes;
      
      optionsChanged();
    }

    public void valueChanged(ListSelectionEvent e) {
      super.valueChanged(e);
      
      valueChanged();
    }

    private void valueChanged() {
      if ((selectedNodeIndex != -1) && (panel != null)) {
        panel.onExit(nodes[selectedNodeIndex]);
      }
      int i = this.getSelectedRow();
      if ((i != -1) && (panel != null)) {
        panel.onEntry(nodes[i]);
        selectedNodeIndex = i;
      }
    }
  }


  public boolean isOkPressed() {
    return this.okPressed;
  }

  public CreateMethodContext[] getNodes() {
    return this.nodes;
  }

  public class MethodTableRenderer extends DefaultTableCellRenderer {

    public Component getTableCellRendererComponent(JTable table,
        Object value,
        boolean isSelected,
        boolean hasFocus,
        int row,
        int column) {
      Component component = super.getTableCellRendererComponent(table, value,
          isSelected, hasFocus, row, column);

      CreateMethodContext node = getNodes()[row];
      if (!node.checkReturnType()) {
        component.setForeground(Color.red);
      } else {
        component.setForeground(table.getForeground());
      }
      return component;
    }
  }
}
